home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HAM Radio 1997
/
HAM Radio 1997.iso
/
vcls
/
wsanet8a
/
wsanet
/
src
/
net.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-04-08
|
32KB
|
1,324 lines
/* Net.C - Generic FIFO queue routines for WSNetC
*/
#include "WSANet.H"
#include "Version.H"
#include "NetClnt.H"
#include "NetSrvr.H"
#include <string.h>
WSADATA wsaData;
static char szError[256];
#ifdef DEBUG_BUILD
VOID DEBUGIO(LPSTR lpString)
{
if(!lpString) return;
wsprintf((LPSTR)szError, (LPSTR)"IO: %s\n\r", lpString);
OutputDebugString( (LPSTR)szError );
}
#else
#define DEBUGIO( parm )
#endif /* DEBUG_BUILD */
/* BOOL netStartup(VOID);
Purpose: To do the nitty gritty net I/O
Given: Nothing.
Returns: TRUE if everything is OK
*/
BOOL netStartup(VOID)
{
WORD wVersionRequested;
DEBUGIO((LPSTR)"netStartup() - Begin");
// Initialize our WinSock.DLL
wVersionRequested=WSA_VERSION_NEEDED;
if(WSAStartup(wVersionRequested, (LPWSADATA)&wsaData))
{
DEBUGIO((LPSTR)"netStartup() - BAD WINSOCK VERSION!");
return(FALSE);
}
if((LOBYTE(wsaData.wVersion)!=1) ||
(HIBYTE(wsaData.wVersion)!=1))
{
WSACleanup();
DEBUGIO((LPSTR)"netStartup() - BAD WINSOCK VERSION!");
return(FALSE);
}
DEBUGIO((LPSTR)"netStartup() - End");
return(TRUE);
} /* netStartup() */
/* VOID netCleanup(VOID);
Purpose: To cleanup after ourselves
*/
VOID netCleanup(VOID)
{
DEBUGIO((LPSTR)"netCleanup()");
WSACleanup();
} /* netCleanup() */
/* BOOL netCloseSocket(HWND, SOCKET);
Purpose: To gracefully close a socket
*/
BOOL netCloseSocket(HWND hWnd, SOCKET sSocket)
{
BOOL bDontLinger;
DEBUGIO((LPSTR)"netCloseSocket() - Begin");
bDontLinger = TRUE;
if((sSocket) && (sSocket != SOCKET_ERROR))
{
if(hWnd) WSAAsyncSelect(sSocket, hWnd,0, 0);
setsockopt(sSocket,
SOL_SOCKET, SO_DONTLINGER, (char FAR *)&bDontLinger,
sizeof(bDontLinger));
closesocket(sSocket);
}
DEBUGIO((LPSTR)"netCloseSocket() - End");
return(FALSE);
}
/* VOID netConnect(HCTL);
Purpose: To decentralize the connect setup code.
*/
BOOL netConnect(HCTL hCtl, SOCKET sSocket)
{
LPNETCLIENT lpNetClient;
int iSendTempSize = DEFAULT_SENDSIZE,
iRecvTempSize = DEFAULT_RECVSIZE;
int iInt = sizeof(iSendTempSize);
HWND hWnd;
DEBUGIO((LPSTR)"netConnect() - Begin");
lpNetClient=(LPNETCLIENT)VBDerefControl(hCtl);
getsockopt(sSocket, SOL_SOCKET, SO_RCVBUF, (LPSTR)&iRecvTempSize,
(int FAR *)&iInt);
getsockopt(sSocket, SOL_SOCKET, SO_SNDBUF, (LPSTR)&iSendTempSize,
(int FAR *)&iInt);
iSendTempSize = max( iSendTempSize, lpNetClient->sSendSize );
iRecvTempSize = max( iRecvTempSize, lpNetClient->sRecvSize );
// Destroy any existing Temporary buffer space
if(lpNetClient->hRecvTemp!=0)
{
GlobalUnlock(lpNetClient->hRecvTemp);
GlobalFree(lpNetClient->hRecvTemp);
}
if(lpNetClient->hSendTemp!=0)
{
GlobalUnlock(lpNetClient->hSendTemp);
GlobalFree(lpNetClient->hSendTemp);
}
// Set new size for temporary space
lpNetClient->sRecvTempSize=(SHORT)iRecvTempSize;
lpNetClient->sSendTempSize=(SHORT)iSendTempSize;
// Allocate the temporary space
lpNetClient->hRecvTemp=GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE,
iRecvTempSize);
lpNetClient->hSendTemp=GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE,
iSendTempSize);
lpNetClient->lpRecvTemp=GlobalLock(lpNetClient->hRecvTemp);
lpNetClient->lpSendTemp=GlobalLock(lpNetClient->hSendTemp);
// Lock and load the receive buffer
lpNetClient->hRecvBuffer=GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE,
lpNetClient->sRecvSize);
if(lpNetClient->hRecvBuffer)
lpNetClient->lpRecvBuffer=GlobalLock(lpNetClient->hRecvBuffer);
// Lock and load the send buffer
lpNetClient->hSendBuffer=GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE,
lpNetClient->sSendSize);
if(lpNetClient->hSendBuffer)
lpNetClient->lpSendBuffer=GlobalLock(lpNetClient->hSendBuffer);
hWnd = VBGetControlHwnd(hCtl);
DEBUGIO((LPSTR)"netConnect() - Calling WSAAsyncSelect()");
WSAAsyncSelect(sSocket, hWnd, CM_NETACTIVITY,
FD_READ | FD_WRITE | FD_CLOSE);
// Flag connection!
lpNetClient->bConnect=TRUE;
VBSetControlProperty(hCtl, IPROP_NETCLIENT_ERRORNUMBER, (LONG)0);
// Let application do what it needs to do.
if(clientFireOnConnect(hCtl))
{
DEBUGIO((LPSTR)"netConnect() - End - FireOnConnect() returned non-0!");
return(TRUE);
}
DEBUGIO((LPSTR)"netConnect() - End");
return(FALSE);
} /* netConnect() */
/* VOID netAccept(HCTL, SOCKET);
Purpose: To decentralize the server accept code.
*/
BOOL netAccept(HCTL hCtl, SOCKET sSocket)
{
LPNETSERVER lpNetServer;
ONACCEPTPARMS Parameters;
SOCKET sNewSocket;
HLSTR hlPeerAddr;
LPSTR lpPeerAddr;
SHORT sRemotePort;
SOCKADDR_IN saPeer;
int iPeer = sizeof(saPeer);
ERR err;
lpNetServer=(LPNETSERVER)VBDerefControl(hCtl);
if(!sSocket) sSocket = lpNetServer->sSocket;
sNewSocket = accept(sSocket, (struct sockaddr FAR *)&saPeer, (LPINT)&iPeer);
if(sNewSocket == INVALID_SOCKET)
{
NetServerError(hCtl, WSAGetLastError());
return(TRUE);
}
sRemotePort = (SHORT)htons(saPeer.sin_port);
lpPeerAddr=inet_ntoa(saPeer.sin_addr);
if(lpPeerAddr == NULL)
{
hlPeerAddr = VBCreateHlstr(NULL, 0);
}
else
{
hlPeerAddr = VBCreateHlstr(lpPeerAddr, lstrlen(lpPeerAddr));
}
Parameters.RemotePort = (SHORT FAR *)&sRemotePort;
Parameters.Socket = (SHORT FAR *)&sNewSocket;
Parameters.PeerAddr = hlPeerAddr;
err = VBFireEvent(hCtl, IEVENT_NETSERVER_ONACCEPT,
(LPVOID)&Parameters);
if(!err)
{
DEBUGIO((LPSTR)"netAccept() - Destroying hlPeerAddr");
VBDestroyHlstr(hlPeerAddr);
// If the user did a "Socket = 0" or "Socket = -1" then closed the
// accepted connection (no NetClient was created to handle it)
if((!sNewSocket)||(sNewSocket==SOCKET_ERROR))
{
netCloseSocket((HWND)NULL, sNewSocket);
DEBUGIO((LPSTR)"netAccept() - Accepted Socket now closed");
}
DEBUGIO((LPSTR)"netAccept() - End");
return(FALSE);
}
else
{
DEBUGIO((LPSTR)"netAccept() - VBFireEvent() returned non-0!");
return(TRUE);
}
} /* netAccept() */
/* LONG netServerAsyncProc(HWND, HCTL, WPARAM, LPARAM);
Purpose: To handle asyncronous WinSock server transactions
*/
LONG netServerAsyncProc(HCTL hCtl, HWND hWnd, WPARAM wParam, LPARAM lParam)
{
LPNETSERVER lpNetServer;
lpNetServer=(LPNETSERVER)VBDerefControl(hCtl);
DEBUGIO((LPSTR)"netServerAsyncProc() - Begin");
if(WSAGETSELECTERROR(lParam))
{
NetServerError(hCtl, WSAGETSELECTERROR(lParam));
}
switch(WSAGETSELECTEVENT(lParam))
{
/*************** FD_ACCEPT ****************/
case FD_ACCEPT:
{
DEBUGIO((LPSTR)"netServerAsyncProc() - FD_ACCEPT - Begin");
if(lpNetServer->sSocket != (SOCKET)wParam)
{
DEBUGIO((LPSTR)"netServerAsyncProc() - FD_ACCEPT - A child socket accept()ed!");
return(ERR_None);
}
// Setup buffers & such
netAccept(hCtl,(SOCKET)wParam);
DEBUGIO((LPSTR)"netServerAsyncProc() - FD_ACCEPT - End");
return(ERR_None);
}
break; /* FD_ACCEPT */
/*************** DEFAULT ******************/
default:
{
char szError[256];
wsprintf((LPSTR)szError, (LPSTR)"netServerAsyncProc: Unhandled WSA message #%d",
wParam);
DEBUGIO((LPSTR)szError);
}
}
DEBUGIO((LPSTR)"netServerAsyncProc() - End");
return(0L);
} /* netServerAsyncProc() */
/* LONG netClientAsyncProc(HWND, HCTL, WPARAM, LPARAM);
Purpose: To handle asyncronous WinSock client transactions.
*/
LONG netClientAsyncProc(HCTL hCtl, HWND hWnd, WPARAM wParam, LPARAM lParam)
{
LPNETCLIENT lpNetClient;
lpNetClient=(LPNETCLIENT)VBDerefControl(hCtl);
DEBUGIO((LPSTR)"netClientAsyncProc() - Begin");
if(WSAGETSELECTERROR(lParam))
{
NetClientError(hCtl, WSAGETSELECTERROR(lParam));
}
switch(WSAGETSELECTEVENT(lParam))
{
/*************** FD_CONNECT ****************/
case FD_CONNECT:
{
DEBUGIO((LPSTR)"netClientAsyncProc() - FD_CONNECT - Begin");
// Setup buffers & such
netConnect(hCtl,(SOCKET)wParam);
DEBUGIO((LPSTR)"netClientAsyncProc() - FD_CONNECT - End");
return(ERR_None);
}
break; /* FD_CONNECT */
/*************** FD_READ ****************/
case FD_READ:
{
int iCount;
DEBUGIO((LPSTR)"netClientAsyncProc() - FD_READ - Begin");
if((!lpNetClient->sSocket) || (lpNetClient->sSocket == SOCKET_ERROR))
{
DEBUGIO((LPSTR)"netClientAsyncProc() - FD_READ - End - sSocket is invalid!");
return(ERR_None);
}
if(lpNetClient->lpRecvBuffer)
{
iCount = netRecvData(hCtl);
}
else return(netReturnError( WSAERR_RecvBuffer,
WSAERR_RecvBuffer, NULL ));
if(iCount==SOCKET_ERROR)
{
int iError;
iError = WSAGetLastError();
switch(iError)
{
case WSAECONNRESET:
// Peer reset connection
return(clientFireOnClose(hCtl));
case WSAEINPROGRESS:
case WSAEWOULDBLOCK:
return(ERR_None);
default:
return(NetClientError( hCtl, WSAGetLastError()));
}
}
if(iCount==0)
{
struct linger lLinger;
DEBUGIO((LPSTR)"netClientAsyncProc() - FD_READ - recv() returned 0! Closing connection.");
lpNetClient=(LPNETCLIENT)VBDerefControl(hCtl);
if(lpNetClient->sSocket != SOCKET_ERROR)
{
netCloseSocket(hWnd, lpNetClient->sSocket);
lpNetClient->bConnect=FALSE;
lpNetClient->sSocket=(SOCKET)SOCKET_ERROR;
}
return(clientFireOnClose(hCtl));
}
// Did we receive enough to cause an event?
if(iCount >= (lpNetClient->sRecvThreshold))
{
return(clientFireOnRecv(hCtl));
}
return(ERR_None);
} /* FD_READ */
/*************** FD_WRITE ***************/
case FD_WRITE:
{
DEBUGIO((LPSTR)"netClientAsyncProc() - FD_WRITE - Begin");
lpNetClient->fCanSend=TRUE;
if(lpNetClient->sSendCount)
{
netSendData(hCtl);
}
DEBUGIO((LPSTR)"netClientAsyncProc() - FD_WRITE - End");
return(ERR_None);
} /* FD_WRITE */
/*************** FD_CLOSE ***************/
case FD_CLOSE:
{
struct linger lLinger;
DEBUGIO((LPSTR)"netClientAsyncProc() - FD_CLOSE - Begin");
if(lpNetClient->lpRecvBuffer)
{
netRecvData(hCtl);
}
if(lpNetClient->sSocket != SOCKET_ERROR)
{
netCloseSocket(hWnd, lpNetClient->sSocket);
lpNetClient->bConnect=FALSE;
lpNetClient->sSocket=(SOCKET)SOCKET_ERROR;
}
lpNetClient->bConnect=FALSE;
// Let the user handle what is left over
clientFireOnRecv(hCtl);
// Let the user handle the closing
clientFireOnClose(hCtl);
DEBUGIO((LPSTR)"netClientAsyncProc() - FD_CLOSE - End");
return(ERR_None);
} /* FD_CLOSE */
default:
{
char szError[256];
wsprintf((LPSTR)szError, (LPSTR)"netClientAsyncProc: Unknown message #%d",
wParam);
DEBUGIO((LPSTR)szError);
}
}
DEBUGIO((LPSTR)"netClientAsyncProc() - End");
return(0L);
} /* netClientAsyncProc() */
/* ERR netSendData(HCTL);
Purpose: To send data pending in the send queue to the sSocket
Given: The VB control handle
Returns: ERR_None or a VB/Control error
*/
ERR netSendData(HCTL hCtl)
{
char szError[256];
LPSTR lpBuffer,
lpWalker,
lpEnd,
lpTemp;
int iSent,
iCount;
SOCKET sSocket;
LPNETCLIENT lpNetClient;
DEBUGIO((LPSTR)"netSendData() - Begin");
if(!hCtl)
{
DEBUGIO((LPSTR)"netSendData() - End - hCtl was 0!");
return(ERR_None);
}
lpNetClient=(LPNETCLIENT)VBDerefControl(hCtl);
if(!(lpNetClient->fCanSend))
{
DEBUGIO((LPSTR)"netSendData() - End - Can't send data! Waiting for FD_WRITE");
return(ERR_None); // No FD_WRITE received yet
}
iCount=lpNetClient->sSendCount;
lpBuffer=lpNetClient->lpSendBuffer;
lpTemp=lpNetClient->lpSendTemp;
sSocket=lpNetClient->sSocket;
if((!sSocket)||(sSocket == SOCKET_ERROR))
{
DEBUGIO((LPSTR)"netSendData() - End - Socket is invalid!");
return(ERR_None);
}
if(!iCount)
{
DEBUGIO((LPSTR)"netSendData() - End - Nothing to send!");
return(ERR_None);
}
if(!lpBuffer)
{
DEBUGIO((LPSTR)"netSendData() - End - No Send buffer!");
return(ERR_None);
}
while(iCount > 0)
{
iSent=send(sSocket, lpBuffer, iCount, 0);
if(iSent==SOCKET_ERROR)
{ // If something was blocking, always try again
iSent=WSAGetLastError();
switch(iSent)
{
case WSAEWOULDBLOCK:
{
MSG Msg;
lpNetClient->fCanSend = FALSE;
DEBUGIO((LPSTR)"netSendData() - End - Overflow (WSAEWOULDBLOCK) - Waiting for FD_WRITE");
// Let other applications take over (somehow this is needed)
PeekMessage(&Msg, NULL, 0, 0, PM_NOREMOVE);
return(ERR_None); // Mark that this happened!
}
case WSAEINPROGRESS:
{
DEBUGIO((LPSTR)"netSendData() - End - Non-fatal error (WSAEINPROGRESS)");
return(ERR_None); // No real error condition exists
}
default:
{
DEBUGIO((LPSTR)"netSendData() - Fatal error");
return(NetClientError(hCtl, iSent));
}
}
}
DEBUGIO((LPSTR)"netSendData() - Sent data");
wsprintf((LPSTR)szError,
(LPSTR)"netSendData() - lpBuffer=%lX iSent=%X iCount=%X",
lpBuffer, iSent, iCount);
DEBUGIO((LPSTR)szError);
/*lpWalker=lpBuffer+iSent;
lpEnd=lpBuffer+iCount;
while(lpWalker<lpEnd)
{
*lpBuffer++=*lpWalker++;
}
// lpBuffer[0] = '\0';
*/
iCount-=iSent;
_fmemmove(lpBuffer, (lpBuffer+iSent), (size_t)iCount);
DEBUGIO((LPSTR)"netSendData() - Copied more to buffer");
lpNetClient->sSendCount=(SHORT)iCount;
// Has threshold been reached?
if(iCount < lpNetClient->sSendThreshold)
{
ERR err;
DEBUGIO((LPSTR)"netSendData() - Threshold reached!");
clientFireOnSend(hCtl);
if(!err)
{ // Refresh all of our local vars.
lpNetClient=(LPNETCLIENT)VBDerefControl(hCtl);
iCount=lpNetClient->sSendCount;
lpBuffer=lpNetClient->lpSendBuffer;
lpTemp=lpNetClient->lpSendTemp;
sSocket=lpNetClient->sSocket;
if((!sSocket) || (sSocket == SOCKET_ERROR))
{
DEBUGIO((LPSTR)"netSendData() - End - After firing OnSend(), Socket became invalid");
return(ERR_None);
}
}
else return(ERR_None);
}
}
DEBUGIO((LPSTR)"netSendData() - End");
return(ERR_None);
} /* netSendData() */
/* int netRecvData(HCTL);
Purpose: To recv data pending on a socket and stuff it in the
recv queue
Given: A VB control structure
Returns: Nothing
Does: Magic
*/
int netRecvData(HCTL hCtl)
{
LPSTR lpBuffer,
lpTemp;
int iReceived,
iCount,
iSize;
SOCKET sSocket;
LPNETCLIENT lpNetClient;
char szErrors[256];
DEBUGIO((LPSTR)"netRecvData() - Begin");
lpNetClient=(LPNETCLIENT)VBDerefControl(hCtl);
if(!lpNetClient)
{
DEBUGIO((LPSTR)"netRecvData() - VBDerefControl() returned NULL!!! Call in the troops!");
return(SOCKET_ERROR);
}
iCount=lpNetClient->sRecvCount;
if(iCount==-1) iCount=0;
lpBuffer=lpNetClient->lpRecvBuffer;
lpTemp=lpBuffer+iCount;
iSize=lpNetClient->sRecvSize;
sSocket=lpNetClient->sSocket;
if(!lpBuffer)
{
// Keep the messages coming
DEBUGIO((LPSTR)"netRecvData() - No receive buffer!");
recv(lpNetClient->sSocket, NULL, 0, 0);
DEBUGIO((LPSTR)"netRecvData() - End - non-fatal");
return(SOCKET_ERROR);
}
if((!sSocket)||(sSocket==SOCKET_ERROR))
{
DEBUGIO((LPSTR)"netRecvData() - End - Socket is not valid!");
return(SOCKET_ERROR);
}
DEBUGIO((LPSTR)"netRecvData() - Debugging information");
wsprintf((LPSTR)szErrors, (LPSTR)"netRecvData() - iCount=%d, iSize=%d",
iCount, iSize);
DEBUGIO((LPSTR)szErrors);
wsprintf((LPSTR)szErrors, (LPSTR)"netRecvData() - sSocket=%d, lpTemp=%lX",
sSocket, lpTemp);
DEBUGIO((LPSTR)szErrors);
if(!lpTemp) return(SOCKET_ERROR);
DEBUGIO((LPSTR)"netRecvData() - Calling recv()");
iReceived=recv(sSocket, lpTemp,
iSize-iCount, 0);
wsprintf((LPSTR)szErrors, (LPSTR)"netRecvData() - recv()==%d", iReceived);
DEBUGIO((LPSTR)szErrors);
DEBUGIO((LPSTR)"netRecvData() - Marker #0");
if(iReceived==SOCKET_ERROR)
{ // If something was blocking, always try again
iReceived=WSAGetLastError();
if((iReceived!=WSAEINPROGRESS) &&
(iReceived!=WSAEWOULDBLOCK))
{
DEBUGIO((LPSTR)"netRecvData() - Marker #1");
NetClientError(hCtl, iReceived);
DEBUGIO((LPSTR)"netRecvData() - Fatal error");
return(SOCKET_ERROR);
}
DEBUGIO((LPSTR)"netRecvData() - Non-fatal error");
return(SOCKET_ERROR);
}
DEBUGIO((LPSTR)"netRecvData() - Marker #2");
if(iReceived==-1)
{
DEBUGIO((LPSTR)"netRecvData() - iReceived==-1! Impossible!!!!");
return(0);
}
if(!iReceived)
{
DEBUGIO((LPSTR)"netRecvData() - iReceived==0! - returning 0");
return(0);
}
DEBUGIO((LPSTR)"netRecvData() - Marker #3");
iCount+=iReceived;
lpNetClient->sRecvCount=(SHORT)iCount;
DEBUGIO((LPSTR)"netRecvData() - End");
return(iCount);
} /* netRecvData() */
/* int putSendData(HCTL, MOLE);
Purpose: To stuff data into the send queue
Given: A VB control structure
A VB handled string - Not destroyed
Returns: Send queue size.
Does: Magic.
*/
int putSendData(HCTL hCtl, MOLE mMole)
{
LPSTR lpBuffer,
lpStrEnd,
lpBufEnd,
lpWalker,
lpStr,
lpTemp;
LPNETCLIENT lpNetClient;
int iSize,
iCount;
USHORT uRemaining,
uStrLen;
char szErrors[256];
DEBUGIO((LPSTR)"putSendData() - Begin");
if(!hCtl)
{
DEBUGIO((LPSTR)"putSendData() - End - hCtl is 0!");
return(SOCKET_ERROR);
}
if(!mMole)
{
DEBUGIO((LPSTR)"putSendData() - End - mMole is 0!");
return(SOCKET_ERROR);
}
lpNetClient=(LPNETCLIENT)VBDerefControl(hCtl);
iSize=lpNetClient->sSendSize;
iCount=lpNetClient->sSendCount;
lpBuffer=lpNetClient->lpSendBuffer;
lpTemp=lpBuffer+iCount;
if(!lpBuffer)
{
DEBUGIO((LPSTR)"putSendData() - No send buffer!");
return(SOCKET_ERROR);
}
if(iCount > iSize)
{
DEBUGIO((LPSTR)"putSendData() - SendCount is greater than SendSize!");
return(SOCKET_ERROR);
}
uRemaining=(USHORT)(iSize-iCount);
uStrLen=VBGetHlstrLen((HLSTR)mMole);
if(!uStrLen)
{
DEBUGIO((LPSTR)"putSendData() - uStrLen = 0!");
return(0);
}
wsprintf((LPSTR)szErrors, (LPSTR)"putSendData() - mMole=%X, uStrLen=%X",
mMole, uStrLen);
DEBUGIO((LPSTR)szErrors);
// Watch for buffer overflow
if(uRemaining && uStrLen>uRemaining)
{
DEBUGIO((LPSTR)"putSendData() - Trying to make buffer room");
netSendData(hCtl);
DEBUGIO((LPSTR)"putSendData() - Marker #2");
lpNetClient=(LPNETCLIENT)VBDerefControl(hCtl);
iCount=lpNetClient->sSendCount;
DEBUGIO((LPSTR)"putSendData() - Marker #4");
uRemaining=(USHORT)(iSize-iCount);
}
if(uRemaining && uStrLen>uRemaining)
{
DEBUGIO((LPSTR)"putSendData() - End - Overflow!!!");
return(SOCKET_ERROR);
}
DEBUGIO((LPSTR)"putSendData() - Enough room, now filling");
GetMoleName(mMole, lpTemp, iSize - iCount);
/* lpStrEnd=lpStr+uStrLen;
lpBufEnd=lpBuffer+iSize;
lpWalker=lpTemp;
while((lpStr<lpStrEnd) && (lpWalker<lpBufEnd))
{
*lpWalker++=*lpStr++;
}
*lpWalker='\0';
*/
iCount+=uStrLen;
lpNetClient=(LPNETCLIENT)VBDerefControl(hCtl);
lpNetClient->sSendCount=(SHORT)iCount;
// If we can, flush some
DEBUGIO((LPSTR)"putSendData() - trying to send data out of turn");
netSendData(hCtl);
DEBUGIO((LPSTR)"putSendData() - End");
return(uStrLen);
} /* putSendData() */
/* HLSTR getRecvData(HCTL);
Purpose: To get a block of data in VB string form from the recv
queue.
Given: VB control handle
Returns: A VB HLSTR holding the data.
Note: This routine receives all or nothing, and it will return
embedded NULLs that were received.
*/
HLSTR getRecvData(HCTL hCtl)
{
LPSTR lpBuffer;
int iCount;
LPNETCLIENT lpNetClient;
HLSTR hlReturn;
DEBUGIO((LPSTR)"getRecvData() - Begin");
lpNetClient=(LPNETCLIENT)VBDerefControl(hCtl);
iCount=lpNetClient->sRecvCount;
if(!iCount)
{
DEBUGIO((LPSTR)"getRecvData() - RecvBuffer is logically empty!");
return(VBCreateHlstr(NULL, 0));
}
lpBuffer=lpNetClient->lpRecvBuffer;
hlReturn=VBCreateHlstr(lpBuffer, (USHORT)iCount);
// Did the VB string get created?
if(hlReturn)
{ // then update the internal count
lpNetClient=(LPNETCLIENT)VBDerefControl(hCtl);
lpNetClient->sRecvCount=0;
}
DEBUGIO((LPSTR)"getRecvData() - End - Cross your fingers");
return(hlReturn);
} /* getRecvData() */
/* HSZ getRecvLine(HCTL);
Purpose: To get a line of data from the queue. Will only return a
non-null string if it finds the LineDelimiter sequence.
Given: A VB control handle
Returns: A VB Null terminated string - cannot/will-not include
any nulls (must use getRecvData).
*/
HSZ getRecvLine(HCTL hCtl)
{
LPSTR lpBuffer,
lpDelim,
lpEnd,
lpBufEnd,
lpWalker,
lpKeep,
lpTemp;
int iFound,
iCount,
iRemaining,
iSize;
HSZ hszDelim;
HSZ hszReturn;
BOOL bEnd;
char cChar;
LPNETCLIENT lpNetClient;
DEBUGIO((LPSTR)"getRecvLine() - Begin");
cChar='\0';
lpNetClient=(LPNETCLIENT)VBDerefControl(hCtl);
iCount=lpNetClient->sRecvCount;
if(!iCount)
{
DEBUGIO((LPSTR)"getRecvLine() - Logically empty! Returning empty HSZ");
return(VBCreateHsz((_segment)hCtl, (LPSTR)&cChar));
}
iSize=lpNetClient->sRecvSize;
lpBuffer=lpNetClient->lpRecvBuffer;
if(!lpBuffer)
{
DEBUGIO((LPSTR)"getRecvLine() - No RecvBuffer!!!");
return(VBCreateHsz((_segment)hCtl,
(LPSTR)&cChar));
}
// Lock in the delimiter string
hszDelim=lpNetClient->hszRawLineDelimiter;
if(hszDelim)
{
lpDelim=VBLockHsz(hszDelim);
if(lpDelim)
{
DEBUGIO((LPSTR)"getRecvLine() - RawDelim locked Pointer is valid");
}
}
else
{
DEBUGIO((LPSTR)"getRecvLine() - No RawDelim string!");
lpDelim=NULL;
}
lpNetClient=(LPNETCLIENT)VBDerefControl(hCtl);
bEnd=FALSE;
if(!lpDelim)
{
bEnd=TRUE;
}
else if(!*lpDelim)
{
bEnd=TRUE;
}
if(bEnd)
{
if(hszDelim) VBUnlockHsz(hszDelim);
DEBUGIO((LPSTR)"getRecvLine() - End - Everything returned! (No delimiter)");
lpBuffer[iCount]='\0';
hszReturn=VBCreateHsz((_segment)hCtl, (LPSTR)lpBuffer);
if(hszReturn)
{
lpNetClient=(LPNETCLIENT)VBDerefControl(hCtl);
lpNetClient->sRecvCount=0;
return(hszReturn);
}
return(VBCreateHsz((_segment)hCtl, (LPSTR)&cChar));
}
lpBufEnd=lpBuffer+iCount;
lpTemp=lpBuffer;
DEBUGIO((LPSTR)"getRecvLine() - Searching buffer:");
//DEBUGIO(lpTemp);
while(lpTemp<lpBufEnd)
{
//DEBUGIO() replacement on next line
#ifdef DEBUG_BUILD
OutputDebugString((LPSTR)"*");
#endif // DEBUG_BUILD
// How did a null get in here?!?!
if(!*lpTemp)
{
//DEBUGIO((LPSTR)"Embedded Chr$(0) found in input");
lpTemp++;
continue;
}
// Is there a 1st character match?
if(*lpDelim==*lpTemp)
{
lpKeep=lpTemp;
//DEBUGIO((LPSTR)"First character delimiter match!");
lpWalker=lpDelim;
// While the delimiting string continues...
while(*lpWalker)
{
// Walk with the matches, stop if not
if(*lpWalker==*lpTemp)
{
lpWalker++;
lpTemp++;
}
else break;
}
// Is the delimiter at it's end?
if(!*lpWalker)
{
DEBUGIO((LPSTR)"getRecvLine() - Matched delimiter!");
*lpKeep='\0'; // Overwrite first byte of matched delimiter
hszReturn=VBCreateHsz((_segment)hCtl, lpBuffer);
// If a string was created earlier, return it!
if(hszReturn)
{
DEBUGIO((LPSTR)"getRecvLine() - Successful HSZ created!");
// Calculate bytes remaining
// 0x0000 <cr> lpKeep lpBuffer
// 0x0001 <lf>
// 0x0002 lpTemp
iFound = lpTemp-lpBuffer;
iCount-=iFound;
// Prevent wrap around!!!!
if(iCount < 0)
{
DEBUGIO((LPSTR)"getRecvLine() - Underflow!!!!!");
if(hszDelim) VBUnlockHsz(hszDelim);
return(VBCreateHsz((_segment)hCtl, (LPSTR)&cChar));
}
lpNetClient=(LPNETCLIENT)VBDerefControl(hCtl);
lpNetClient->sRecvCount=(SHORT)iCount;
if(iCount > 0)
{
// Copy used buffer down to overlap where it was
DEBUGIO((LPSTR)"getRecvLine() - DEBUG: _fmemmove()");
_fmemmove(lpBuffer, lpTemp, iCount);
}
DEBUGIO((LPSTR)"getRecvLine() - Returning string");
VBUnlockHsz(hszDelim);
return(hszReturn);
}
}
else
{
lpTemp=lpKeep;
}
}
lpTemp++;
}
// Didn't find the delimiter string
VBUnlockHsz(hszDelim);
cChar=0;
DEBUGIO((LPSTR)"getRecvLine() - End - Nothing returned!");
return(VBCreateHsz((_segment)hCtl, (LPSTR)&cChar));
} /* getRecvLine() */
// Declare Function NetClientSendBlock Lib "WSNETC.VBX" /
// (cControl As NetClient, sString As String) As Integer
/* int CALLBACK _export NetClientSendBlock(HCTL hCtl, HLSTR);
Purpose: To return a "block" string from the recv queue.
Given: The handle of the control to use
The string to send
Returns: The number of characters sent
*/
int CALLBACK _export NetClientSendBlock(HCTL hCtl, HLSTR hlStr)
{
DEBUGIO((LPSTR)"NetClientSendBlock()");
return(putSendData(hCtl, hlStr));
} /* NetClientSendBlock() */
// Declare Function NetClientRecvBlock Lib "WSNETC.VBX" /
// (cControl As NetClient, sString As String, iNumber As Integer) As Integer
/* HLSTR CALLBACK _export NetClientRecvBlock(int);
Purpose: To return a "block" string from the recv queue.
Given: A NetClient control
A VB String
The number of characters to grab, or 0 for everything
Returns: 0 if everything went ok, an error if not
*/
int CALLBACK _export NetClientRecvBlock(HCTL hCtl, HLSTR hlStr, int iNumber)
{
LPNETCLIENT lpNetClient;
LPSTR lpBuffer;
int iCount;
HLSTR hlTemp;
ERR err;
DEBUGIO((LPSTR)"NetClientRecvBlock() - Begin");
lpNetClient=(LPNETCLIENT)VBDerefControl(hCtl);
iCount=lpNetClient->sRecvCount;
if(iNumber==0) iNumber=iCount;
if(iNumber>iCount) iNumber=iCount;
hlTemp = hlStr;
if(!iCount)
{
DEBUGIO((LPSTR)"NetClientRecvBlock() - RecvBuffer is logically empty!");
VBSetHlstr((LPHLSTR)&hlTemp, NULL, 0);
return(0);
}
lpBuffer=lpNetClient->lpRecvBuffer;
err = VBSetHlstr((LPHLSTR)&hlTemp, (LPVOID)lpBuffer, (SHORT)iNumber);
if(!err)
{
lpNetClient=(LPNETCLIENT)VBDerefControl(hCtl);
lpNetClient->sRecvCount=(SHORT)(iCount - iNumber);
}
DEBUGIO((LPSTR)"NetClientRecvBlock() - End - Cross your fingers ;)");
return(err);
} /* NetClientRecvBlock() */
/* ERR netReturnError(ERR, int, LPSTR);
Purpose: To set the text for a VB error, and return
*/
ERR netReturnError(ERR eError, int iResource, LPSTR lpMessage)
{
static szString[128];
DEBUGIO((LPSTR)"netReturnError()");
// Resource #0 means use default text for error
if(lpMessage == NULL)
{
if(iResource == 0) return(eError);
if(!LoadString(hModDLL, iResource, (LPSTR)szString,
sizeof(szString)))
{
wsprintf((LPSTR)szString, (LPSTR)"Unknown Error #%d: Resource string #%d missing",
eError, iResource);
}
return(VBSetErrorMessage(eError, (LPSTR)szString));
}
else
return(VBSetErrorMessage(eError, lpMessage));
} /* netReturnError() */
/* HSZ GetMoleHsz(HCTL, MOLE);
Purpose: To convert an MOLE string to a VB HSZ string.
Note: This is a little out of place, but this module is
common to all of the others.
*/
HSZ GetMoleHsz(HCTL hCtl, MOLE mMole)
{
static szBuffer[256];
HSZ hszTemp;
LPSTR lpTemp;
char cChar;
USHORT uLength;
DEBUGIO((LPSTR)"GetMoleHsz() - Begin");
if(mMole)
{
uLength = VBGetHlstrLen((HLSTR)mMole);
#ifdef DEBUG_BUILD
wsprintf((LPSTR)szBuffer, (LPSTR)"uLength=%X", uLength);
DEBUGIO((LPSTR)szBuffer);
#endif
lpTemp = VBDerefHlstr((HLSTR)mMole);
if(lpTemp)
{
lstrcpyn((LPSTR)szBuffer, lpTemp, uLength);
szBuffer[uLength+1] = '\0';
DEBUGIO((LPSTR)szBuffer);
hszTemp=VBCreateHsz((_segment)hCtl, (LPSTR)szBuffer);
DEBUGIO((LPSTR)"GetMoleHsz() - End - Built valid HSZ");
return(hszTemp);
}
}
cChar = '\0';
hszTemp=VBCreateHsz((_segment)hCtl, (LPSTR)&cChar);
DEBUGIO((LPSTR)"GetMoleHsz() - End - Returned an empty string!");
return(hszTemp);
} /* GetMoleHsz() */
/* VOID GetMoleName(MOLE, LPSTR, int);
Purpose: To convert an MOLE string to a C string.
Note: This is a little out of place, but this module is
common to all of the others.
*/
VOID GetMoleName(MOLE mMole, LPSTR lpString, int iSize)
{
static szBuffer[256];
LPSTR lpTemp;
size_t stCount;
//DEBUGIO((LPSTR)"GetMoleName() - Begin");
if(!lpString) return;
if(!iSize) return;
if(mMole)
{
stCount = (size_t)VBGetHlstrLen((HLSTR)mMole);
if(stCount > (size_t)iSize)
{
DEBUGIO((LPSTR)"GetMoleName() - I don't have enough room to hold it all!");
stCount = (size_t)iSize;
}
lpTemp = VBDerefHlstr((HLSTR)mMole);
if(lpTemp)
{
_fmemmove(lpString, lpTemp, stCount);
//DEBUGIO((LPSTR)"GetMoleName() - End - Success!");
return;
}
}
*lpString = '\0';
DEBUGIO((LPSTR)"GetMoleName() - End - Returned an empty string!");
return;
} /* GetMoleName() */
/* VOID SetMole(MOLE, LPSTR);
Purpose: To set the handed MOLE to the handed LPSTR.
*/
VOID SetMole(LPMOLE pmMole, LPSTR lpString)
{
HLOCAL hLocal;
LPSTR lpTemp;
DEBUGIO((LPSTR)"SetMole() - Begin");
if(!lpString)
{
DEBUGIO((LPSTR)"SetMole() - End - lpString was NULL");
return;
}
if(VBSetHlstr((LPHLSTR)pmMole, lpString, lstrlen(lpString) + 1))
{
DEBUGIO((LPSTR)"SetMole() - VBSetHlstr() failed!");
}
else
{
DEBUGIO((LPSTR)"SetMole() - VBSetHlstr() was successful!");
}
DEBUGIO((LPSTR)"SetMole() - End");
return;
} /* SetMole() */
/* MOLE AddMole(LPSTR);
Purpose: To create a new MOLE for an LPSTR.
*/
MOLE AddMole(LPSTR lpString)
{
MOLE mTemp;
//DEBUGIO((LPSTR)"AddMole() - Begin");
mTemp = CreateMole(lpString , (USHORT)(lstrlen(lpString) + 1));
//DEBUGIO((LPSTR)"AddMole() - End");
return(mTemp);
} /* AddMole() */
/* MOLE CreateMole(LPSTR, int);
Purpose: To allow set length Mole's
*/
MOLE CreateMole(LPSTR lpString, USHORT uLength)
{
HLSTR hlStr;
DEBUGIO((LPSTR)"CreateMole() - Begin");
if(!lpString)
{
DEBUGIO((LPSTR)"CreateMole() - End - lpString was NULL");
return((MOLE)0);
}
hlStr = VBCreateHlstr(lpString, uLength);
if(hlStr)
{
DEBUGIO((LPSTR)"CreateMole() - VBCreateHlstr() Succeeded!");
}
else
{
DEBUGIO((LPSTR)"CreateMole() - VBCreateHlstr() Failed!");
}
DEBUGIO((LPSTR)"CreateMole() - End");
return((MOLE)hlStr);
} /* CreateMole() */
/* VOID DeleteMole(LPMOLE);
Purpose: To delete the handed MOLE
*/
VOID DeleteMole(MOLE mMole)
{
//DEBUGIO((LPSTR)"DeleteMole() - Begin");
if(mMole)
{
VBDestroyHlstr((HLSTR)mMole);
DEBUGIO((LPSTR)"DeleteMole() - End");
return;
}
//DEBUGIO((LPSTR)"DeleteMole() - End - Mole was 0!");
} /* DeleteMole() */
/* END of Net.C */